#!/usr/bin/env python
# -*- coding: UTF-8 -*-

import os
import sys
import shutil
import tempfile

execfile(os.path.join(sys.path[0], "framework.py"))

from oriolus.pith.packets.meta import Meta
from oriolus.pith.packets.script import Script
from oriolus.pith.packets.packet import Packet, RemovePacket, FilePacket, FullName, FullNameParseError, Status
from unittest import TestCase, TestLoader, TextTestRunner

class TestPacket(TestCase):
    def test_file_packet(self):
        packet_path = os.path.join(".", "testdata", "test_packet-1.2.3.4.zip.ori")
        file_packet = FilePacket(packet_path)
        self.assertEqual("test_packet-1.2.3.4", file_packet.name)
        self.__assertMetaEqual(Meta("test_packet", "1.2.3.4", "Test packet", [], [], []), file_packet.meta)
        self.assertEqual(Status.NEW, file_packet.status)
        expected_script_names = ("install", "postinstall", "preinstall", "remove", "postremove", "preremove")
        self.assertEqual(len(expected_script_names), len(file_packet.scripts))
        map(lambda script: self.assertTrue(os.path.exists(script.path)), file_packet.scripts)
        map(lambda script: self.assertTrue(script.name in expected_script_names), file_packet.scripts)    
    
    def test_file_packet_with_relative_path(self):
        dir = tempfile.mkdtemp()
        try:
            packet_path = os.path.join(".", "testdata", "test_packet-1.2.3.4.zip.ori")
            file_packet = FilePacket(packet_path, dir)
            self.assertEqual("test_packet-1.2.3.4", file_packet.name)
            self.__assertMetaEqual(Meta("test_packet", "1.2.3.4", "Test packet", [], [], []), file_packet.meta)
            self.assertEqual(Status.NEW, file_packet.status)
            expected_script_names = ("install", "postinstall", "preinstall", "remove", "postremove", "preremove")
            self.assertEqual(len(expected_script_names), len(file_packet.scripts))
            map(lambda script: self.assertTrue(os.path.exists(script.path)), file_packet.scripts)
            map(lambda script: self.assertTrue(script.name in expected_script_names), file_packet.scripts)
            self.assertEqual(dir, file_packet.basepath)
            path_builder = lambda script: os.path.join(dir, "scripts", script.name + ".py")
            map(lambda script: self.assertEqual(script.path, path_builder(script)), file_packet.scripts)
        finally:
            shutil.rmtree(dir) 
            
#    def test_file_packet_with_relative_path2(self):
#        dir = r"C:\tmp_dir"
#        packet_path = r"C:\ProgramData\cache"
#        #names = ["DBus-net35-1.0.0.0"]
#        names = os.listdir(packet_path)
#        for i in range(1, 2):
#            for name in names:
#                print name
#                file_packet = FilePacket(os.path.join(packet_path, name), dir)
#                file_packet.dispose()           
    
    def test_full_name_parse1(self):
        packet_name = "test_packet-1.2.3.4"
        full_name = FullName.parse(packet_name)

        self.assertEqual("test_packet", full_name.name)
        self.assertEqual("1.2.3.4", full_name.version)

    def test_full_name_parse2(self):
        packet_name = "test-packet-1.2.3.4"
        full_name = FullName.parse(packet_name)

        self.assertEqual("test-packet", full_name.name)
        self.assertEqual("1.2.3.4", full_name.version)

    def test_full_name_parse3(self):
        packet_name = "test-packet-1.f.3.4"
        self.assertRaises(FullNameParseError, FullName.parse, packet_name)

    def test_packet_status_map(self):
        self.assertEqual(Status.INSTALLED, Status.status_map[Status.INSTALLING])
        self.assertEqual(Status.INSTALLED_AS_DEPENDENCY, Status.status_map[Status.INSTALLING_AS_DEPENDENCY])
        
    def test_remove_packet(self):
        script_names = ("install", "postinstall", "preinstall", "remove", "postremove", "preremove")
        scripts = [Script(name, os.path.join("scripts", name + ".py")) for name in script_names]
        packet = Packet(Meta("test_packet", "1.2.3.4", "Test packet", [], [], []), scripts)
        remove_packet = RemovePacket(packet)
        
        self.assertEqual(packet.name, remove_packet.name)
        self.assertEqual(packet.status, remove_packet.status)
        self.assertEqual(packet.meta, remove_packet.meta)
        self.assertEqual(packet.scripts, remove_packet.scripts)
        self.assertEqual(packet.basepath, remove_packet.basepath)  
    
    def test_remove_packet_with_relative_path(self):
        dir = tempfile.mkdtemp()
        original_copy = shutil.copy
        shutil.copy = lambda x, y: ()
        try:
            script_names = ("install", "postinstall", "preinstall", "remove", "postremove", "preremove")
            scripts = [Script(name, os.path.join("scripts", name + ".py")) for name in script_names]
            packet = Packet(Meta("test_packet", "1.2.3.4", "Test packet", [], [], []), scripts, basepath = dir)
            remove_packet = RemovePacket(packet)
            
            self.assertEqual(packet.name, remove_packet.name)
            self.assertEqual(packet.status, remove_packet.status)
            self.assertEqual(packet.meta, remove_packet.meta)
            self.assertEqual(packet.basepath, remove_packet.basepath) 
            
            path_builder = lambda script: os.path.join(dir, "scripts", script.name + ".py")
            map(lambda script: self.assertEqual(script.path, path_builder(script)), remove_packet.scripts)
            
            self.assertTrue(os.path.exists(os.path.join(dir, "scripts")))
        finally:
            shutil.copy = original_copy
            shutil.rmtree(dir) 

    def __assertMetaEqual(self, expectedMeta, actualMeta):
        self.assertEqual(type(expectedMeta), type(actualMeta))
        publicAttributes = [attr for attr in dir(actualMeta) if not callable(getattr(actualMeta, attr)) and not attr.startswith("__")]
        map(lambda attr: self.assertEqual(getattr(expectedMeta, attr), getattr(actualMeta, attr)), publicAttributes)

if __name__ == "__main__":
    suite = TestLoader().loadTestsFromTestCase(TestPacket)
    TextTestRunner(verbosity=2).run(suite)